package com.imageim.yimirror.common.ui.drawbody;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import com.imageim.yimirror.R;
import com.imageim.yimirror.bean.analysisPhoto.PointBean;
import com.imageim.yimirror.common.data.CommonData;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Bruce.Zhou on 2018/9/17.
 */

public class BodyLineView extends SurfaceView implements Runnable {

    private Paint paint;
    private SurfaceHolder holder;
    private boolean isDrawing;
    private boolean isInited;
    private int lineColor;
    private int lineColorDot;
    private int lineWidth = 3;
    private int bigCircleWidth = 2;
    private BodyLine bodyFullLine1;
    private BodyLine bodyFullLine2;
    private BodyLine bodyDottedLine1;
    private BodyLine bodyDottedLine2;
    private BodyLine bodyDottedLine3;
    private BodyLine bodyIndicatorLine2;
    private BodyLine bodyIndicatorLine4;
    private boolean canDraw;
    private Bitmap indicatorBitmap;
    private Matrix matrix = new Matrix();
    private DashPathEffect dashPathEffect = new DashPathEffect(new float[]{3, 6}, 0);
    //坐标转换比率
    private float currentRate = 1;

    public BodyLineView(Context context) {
        super(context);
        init();
    }

    public BodyLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BodyLineView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (!isInited) {
            isInited = true;
        }
    }

    public boolean isCanDraw() {
        return canDraw;
    }

    public void setCanDraw(boolean canDraw) {
        this.canDraw = canDraw;
    }

    private void init() {
        initData(null);
        initBitmap();
        setClickable(true);
        setEnabled(true);
        lineColor = Color.parseColor("#aa26bdff");
        lineColorDot = Color.parseColor("#8826bdff");
        paint = new Paint();
        paint.setStrokeWidth(lineWidth);
        paint.setTextSize(40);
        paint.setAntiAlias(true);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(lineColor);
        //        paint.setDither(true);
        setZOrderOnTop(true);
        holder = getHolder();
        holder.setFormat(PixelFormat.TRANSLUCENT);
        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                if (isDrawing == false) {
                    isDrawing = true;
                    new Thread(BodyLineView.this).start();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
                isDrawing = false;
            }
        });
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                initData(pointMap);
            }
        });
    } // init()


    private void initBitmap() {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.indicator_bitmap);
        indicatorBitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * 0.6f),
                (int) (bitmap.getHeight() * 0.6f), false);
        bitmap.recycle();
    }

    private Map<String, PointBean> pointMap;


    /**
     * 设置相对于1080*1920分辨率的比率
     * 需要在init之前调用
     *
     * @param rate 比率值 0-1f
     */
    public void setCurrentRate(float rate) {
        this.currentRate = rate;
    }

    public float getCurrentRate() {
        return currentRate;
    }

    public void initData(Map<String, PointBean> pointMap) {
        this.pointMap = pointMap;
        // full line 1
        //        bodyFullLine1 = new BodyLine();
        //        bodyFullLine1.setType(BodyLine.TYPE_DOTTED);
        //        List<BodyPoint> pointList = new ArrayList<>();
        //        BodyPoint point1 = new BodyPoint(160, 100);
        //        point1.setStatus(PointStatus.STATUS_STARTED);
        //        point1.setIndicatorStatus(PointStatus.STATUS_STARTED);
        //        BodyPoint point2 = new BodyPoint(220, 280);
        //        BodyPoint point3 = new BodyPoint(120, 500);
        //        BodyPoint point4 = new BodyPoint(420, 750);
        //        BodyPoint point5 = new BodyPoint(310, 910);
        //        BodyPoint point6 = new BodyPoint(710, 770);
        //        BodyPoint point7 = new BodyPoint(500, 650);
        //        bodyFullLine1.setPointList(pointList);
        //        bodyFullLine1.endX = point1.getX();
        //        bodyFullLine1.endY = point1.getY();
        //        bodyFullLine1.indicatorEndX = point1.getX();
        //        bodyFullLine1.indicatorEndY = point1.getY();
        //        pointList.add(point1);
        //        pointList.add(point2);
        //        pointList.add(point3);
        //        pointList.add(point4);
        //        pointList.add(point5);
        //        pointList.add(point6);
        //        pointList.add(point7);
        // full line 2
        if (pointMap == null) {
            return;
        }
        bodyFullLine1 = createBodyLine("A,B,C,D,E,F,G,H,J", BodyLine.TYPE_FULL, false);
        bodyFullLine2 = createBodyLine("A,B1,C1,D1,E1,F1,G1,H1,J", BodyLine.TYPE_FULL, false);
        // dotted lines
        bodyDottedLine1 = createBodyLine("B,B1,C,C1,E1,F,G1,H,H1", BodyLine.TYPE_DOTTED, false);
        bodyDottedLine2 = createBodyLine("B,C1,E,C,E1,E,F1,G,H1", BodyLine.TYPE_DOTTED, false);
        bodyDottedLine3 = createBodyLine("G,G1", BodyLine.TYPE_DOTTED, false);
        bodyIndicatorLine2 = createBodyLine("J,H1,G1,F1,E1,D1,C1,B1,A", BodyLine.TYPE_DOTTED, true);
        bodyIndicatorLine4 = createBodyLine("H1,G,F1,E,E1,C,E,C1,B", BodyLine.TYPE_DOTTED, true);
    }

    /**
     * @param keys        A,B,C,D... keys至少含有两个值
     * @param lineType
     * @param isIndicator true不绘制线，仅表示indicator运行路径
     * @return
     */
    private BodyLine createBodyLine(String keys, int lineType, boolean isIndicator) {
        if (pointMap == null) {
            return null;
        }
        BodyLine bodyLine = new BodyLine();
        bodyLine.setType(lineType);
        List<BodyPoint> pointList = new ArrayList<>();
        String[] keyArray = keys.split(",");
        for (String key : keyArray) {
            float dstX = convertX(pointMap.get(key).getX()) * currentRate;
            float dstY = convertY(pointMap.get(key).getY()) * currentRate;
            pointList.add(new BodyPoint(dstX, dstY));
        }
        bodyLine.setPointList(pointList);
        BodyPoint startPoint = pointList.get(0);
        if (!isIndicator) {
            startPoint.setStatus(PointStatus.STATUS_STARTED);
            bodyLine.endX = startPoint.getX();
            bodyLine.endY = startPoint.getY();
        }
        startPoint.setIndicatorStatus(PointStatus.STATUS_STARTED);
        bodyLine.indicatorEndX = startPoint.getX();
        bodyLine.indicatorEndY = startPoint.getY();
        return bodyLine;
    }

    private float convertX(float x) {
        float dstX = ((x - CommonData.subDx) * CommonData.bodyScaleRate + CommonData.addDx) * CommonData.finalBodyScaleRate;
        return dstX;
    }

    private float convertY(float y) {
        float dstY = ((y - CommonData.subDY) * CommonData.bodyScaleRate + CommonData.addDy) * CommonData.finalBodyScaleRate;
        return dstY;
    }

    @Override
    public void run() {
        while (isDrawing) {
            draw();
        }
    }

    private void draw() {
        Canvas canvas = holder.lockCanvas();
        if (canvas == null) {
            return;
        }
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        if (canDraw && bodyFullLine1 != null) { // canDraw flag
            // draw a line
            drawLine(canvas, bodyFullLine1);
            drawLine(canvas, bodyFullLine2);
            if (bodyFullLine1.getCurrStartedPointIndex() >= 6 || bodyFullLine1.getCurrStartedPointIndex() == -1) {
                drawLine(canvas, bodyDottedLine1);
                drawLine(canvas, bodyDottedLine2);
                if (bodyDottedLine1.isFinished() && bodyDottedLine2.isFinished()) {
                    drawLine(canvas, bodyDottedLine3);
                }
            }
            // draw indicator
            if (bodyFullLine1.isFinished() && bodyFullLine2.isFinished()
                    && bodyDottedLine1.isFinished() && bodyDottedLine2.isFinished()
                    && bodyDottedLine3.isFinished()) {
                drawIndicator(canvas, bodyFullLine1);
                drawIndicator(canvas, bodyDottedLine1);
                drawIndicator(canvas, bodyIndicatorLine2);
                drawIndicator(canvas, bodyIndicatorLine4);
            }
        }
        if (holder != null) {
            try {
                holder.unlockCanvasAndPost(canvas);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private boolean drawIndicator = true;

    public void setDrawIndicator(boolean drawIndicator) {
        this.drawIndicator = drawIndicator;
    }

    /**
     * @param canvas
     * @param bodyLine indicator路径
     */
    private void drawIndicator(Canvas canvas, BodyLine bodyLine) {
        if (!drawIndicator) {
            return;
        }
        bodyLine.setIndicatorMoveDelta();
        bodyLine.indicatorEndX += bodyLine.moveDeltaX * 2;
        bodyLine.indicatorEndY += bodyLine.moveDeltaY * 2;
        bodyLine.udpateBodyPointIndicatorStatus();

        //            paint.setStyle(Paint.Style.FILL);
        //            paint.setAlpha(200);
        //            canvas.drawCircle(bodyLine.indicatorEndX, bodyLine.indicatorEndY, 10, paint);
        //            paint.setAlpha(255);

        // bitmap
        double degree;
        float transX = 0;
        float transY = 0;
        if (bodyLine.moveDeltaX != 0) {
            degree = Math.toDegrees(Math.atan(Math.abs(bodyLine.moveDeltaY / bodyLine.moveDeltaX)));
            if (bodyLine.moveDeltaX > 0 && bodyLine.moveDeltaY >= 0) {
                degree += 90; // 右下
                transX = bodyLine.indicatorEndX + indicatorBitmap.getWidth() / 2;
                if (bodyLine.moveDeltaY < 1.0f) {
                    transY = bodyLine.indicatorEndY - indicatorBitmap.getWidth() / 2;
                } else {
                    transY = bodyLine.indicatorEndY;
                }
            } else if (bodyLine.moveDeltaX < 0 && bodyLine.moveDeltaY >= 0) {
                degree = -90 - degree; // 左下
                transX = bodyLine.indicatorEndX + indicatorBitmap.getWidth() / 2;
                transY = bodyLine.indicatorEndY;
            } else if (bodyLine.moveDeltaX > 0 && bodyLine.moveDeltaY <= 0) {
                degree = 90 - degree; // 右上
                //                    if (bodyLine.moveDeltaX < 1.3f) {
                //                        transX = bodyLine.indicatorEndX - indicatorBitmap.getWidth()/2;
                //                    } else {
                //                        transX = bodyLine.indicatorEndX;
                //                    }
                transX = bodyLine.indicatorEndX - indicatorBitmap.getWidth() / 2;
                transY = bodyLine.indicatorEndY - indicatorBitmap.getWidth() / 2;
            } else if (bodyLine.moveDeltaX < 0 && bodyLine.moveDeltaY <= 0) {
                degree = degree - 90; // 左上
                transX = bodyLine.indicatorEndX - indicatorBitmap.getWidth() / 2;
                transY = bodyLine.indicatorEndY + indicatorBitmap.getWidth() / 2;
            }
        } else {
            if (bodyLine.moveDeltaY > 0) {
                degree = 180;
                transX = bodyLine.indicatorEndX;
                transY = bodyLine.indicatorEndY;
            } else {
                degree = 0;
                transX = bodyLine.indicatorEndX;
                transY = bodyLine.indicatorEndY;
            }
        }
        matrix.reset();
        matrix.postRotate((float) degree);
        matrix.postTranslate(transX, transY);
        paint.setAlpha(200);
        canvas.drawBitmap(indicatorBitmap, matrix, paint);
        paint.setAlpha(255);
    } // drawIndicator

    private void drawLine(Canvas canvas, BodyLine bodyLine) {
        if (bodyLine == null) {
            return;
        }
        bodyLine.path.reset();
        BodyPoint firstPoint = bodyLine.getPointList().get(0);
        if (bodyLine.getType() == BodyLine.TYPE_FULL) { // 实线绘制圆圈
            drawCircle(canvas, firstPoint);
        }
        bodyLine.path.moveTo(firstPoint.getX(), firstPoint.getY());
        for (int i = 1; i < bodyLine.getPointList().size(); i++) {
            BodyPoint point = bodyLine.getPointList().get(i);
            if (point.getStatus() == PointStatus.STATUS_FINISHED
                    || point.getStatus() == PointStatus.STATUS_STARTED) {
                bodyLine.path.lineTo(point.getX(), point.getY());
                if (bodyLine.getType() == BodyLine.TYPE_FULL) {
                    drawCircle(canvas, point);
                }
            } else {
                break;
            }
        }
        if (!bodyLine.isFinished()) {
            bodyLine.setMoveDelta();
            bodyLine.endX += bodyLine.moveDeltaX;
            bodyLine.endY += bodyLine.moveDeltaY;
            bodyLine.path.lineTo(bodyLine.endX, bodyLine.endY);
            bodyLine.udpateBodyPointStatus();
        }
        if (bodyLine.getAlpha() + 2 < 180) {
            bodyLine.setAlpha(bodyLine.getAlpha() + 2);
        } else {
            bodyLine.setAlpha(180);
        }
        paint.setAlpha(bodyLine.getAlpha());

        if (bodyLine.getType() == BodyLine.TYPE_DOTTED) {
            paint.setPathEffect(dashPathEffect);
            paint.setColor(lineColorDot);
            paint.setStrokeWidth(2);
        }
        canvas.drawPath(bodyLine.path, paint);
        paint.setStrokeWidth(lineWidth);
        paint.setPathEffect(null);
        paint.setAlpha(255);
        paint.setColor(lineColor);
        paint.setStrokeWidth(lineWidth);
    }

    private void drawCircle(Canvas canvas, BodyPoint point) {
        paint.setStyle(Paint.Style.FILL);
        if (point.isBrightUp()) {
            if (point.getAlpha() + 2 < 255) {
                point.setAlpha(point.getAlpha() + 2);
            } else {
                point.setAlpha(255);
                point.setBrightUp(false);
            }
        } else {
            if (point.getAlpha() - 2 >= 128) {
                point.setAlpha(point.getAlpha() - 2);
            } else {
                point.setAlpha(128);
                point.setBrightUp(true);
            }
        }

        paint.setAlpha(point.getAlpha());
        canvas.drawCircle(point.getX(), point.getY(), point.getSmallCircleRadius(), paint);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(bigCircleWidth);
        //        paint.setPathEffect(new DashPathEffect(new float[]{20, 20},0));
        canvas.drawCircle(point.getX(), point.getY(), point.getBigCircleRadius(), paint);
        paint.setStrokeWidth(lineWidth);
        paint.setAlpha(255);
    }


    public void stop() {
        setCanDraw(false);
        isDrawing = false;
    }


    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (indicatorBitmap != null) {
            indicatorBitmap.recycle();
            indicatorBitmap = null;
        }
    }
}
